package service

import (
	"gitee.com/linxing_3/sr-core/domain/dao/scope"
	"gitee.com/linxing_3/sr-core/domain/service/srvctx"
	"gitee.com/mkwchecking/sr-admin/apps/devtools/acl"
	"gitee.com/mkwchecking/sr-admin/apps/devtools/entity"
	"gitee.com/mkwchecking/sr-admin/apps/devtools/repo"
	"gitee.com/mkwchecking/sr-admin/pkg/utils/copy"
)

func NewModuleTable(tableRepo *repo.ModuleTable, fieldRepo *repo.ModuleField, sysDb *repo.SysDB) *ModuleTable {
	return &ModuleTable{
		table: tableRepo,
		field: fieldRepo,
		sysDb: sysDb,
	}
}

type ModuleTable struct {
	table *repo.ModuleTable
	field *repo.ModuleField
	sysDb *repo.SysDB
}

func (s *ModuleTable) Insert(ctx srvctx.IContext, req *acl.ModuleTableInsertReq) error {
	table, err := copy.CopyToG[entity.ModuleTable](req)
	if err != nil {
		return err
	}
	// table.Fields = nil
	_, err = s.table.Create(table, scope.WithConflictUpdateAll("domain", "class_name"))
	if err != nil {
		return err
	}

	// if len(req.Fields) > 0 {
	// 	return s.table.AddFields(req.Domain, req.ClassName, req.Fields...)
	// }
	return nil
}

func (s *ModuleTable) InsertFromDB(ctx srvctx.IContext, req *acl.ImportDBTable) error {
	tb, err := s.sysDb.GetFullTable(req.Schema, req.TableName)
	if err != nil {
		return err
	}

	insertReq := &acl.ModuleTableInsertReq{
		ModuleTable: *tb.ToModuleTable(),
	}
	return s.Insert(ctx, insertReq)
}

func (s *ModuleTable) Update(ctx srvctx.IContext, req *acl.ModuleTableUpdateReq) error {
	table, err := copy.CopyToG[entity.ModuleTable](req)
	if err != nil {
		return err
	}
	_, err = s.table.Update(table, s.table.EntBuilder(func(mt *entity.ModuleTable) {
		mt.ClassName = req.ClassName
		mt.Domain = req.Domain
	}))

	if len(req.Fields) > 0 {
		// s.table.ReplaceFields(req.Domain, req.ClassName, req.Fields...)
		s.field.Replace(req.Domain, req.ClassName, req.Fields...)
	}
	return err
}

func (s *ModuleTable) List(ctx srvctx.IContext, req *acl.ModuleTableListReq) ([]*entity.ModuleTable, int64, error) {
	filter, err := copy.CopyToG[entity.ModuleTable](req)
	if err != nil {
		return nil, 0, err
	}
	ents, total, err := s.table.FindMulti(req.PageNum, req.PageSize, scope.Where(filter))
	return ents, total, err
}

func (s *ModuleTable) Detail(ctx srvctx.IContext, req *acl.ModuleTableDetailReq) (*entity.ModuleTable, error) {
	// filter, err := copy.CopyToG[entity.ModuleTable](req)
	// if err != nil {
	// 	return nil, err
	// }

	ent, err := s.table.FindWithEnt(req, scope.WithPreload("Fields"))
	return ent, err
}

func (s *ModuleTable) Delete(ctx srvctx.IContext, req *acl.ModuleTableDeleteReq) error {
	return s.table.Delete(req.Domain, req.ClassName, true)
}

func (s *ModuleTable) AddField(ctx srvctx.IContext, req *acl.ModuleTableDetailReq) error {
	return s.table.AddFields(req.Domain, req.ClassName, req.Fields...)
}

func (s *ModuleTable) DeleteField(ctx srvctx.IContext, req *acl.ModuleTableRemoveFieldReq) error {
	return s.table.RemoveField(req.Domain, req.ClassName, req.FieldNames...)
}

func (s *ModuleTable) UpdateField(ctx srvctx.IContext, req *acl.ModuleTableUpdateFieldReq) error {
	ent, err := copy.CopyToG[entity.ModuleField](req.Field)
	if err != nil {
		return err
	}

	_, err = s.field.Update(ent, s.field.EntBuilder(func(mf *entity.ModuleField) {
		mf.ClassName = req.ClassName
		mf.Domain = req.Domain
		mf.FieldName = req.Field.FieldName
	}))
	return err
}
